package com.donfelix.looknews.view.activity;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.transition.ChangeBounds;
import android.transition.Transition;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.FrameLayout;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.donfelix.looknews.R;
import com.donfelix.looknews.bean.zhihu.ZhihuStory;
import com.donfelix.looknews.common.BaseActivity;
import com.donfelix.looknews.common.Config;
import com.donfelix.looknews.util.AnimUtils;
import com.donfelix.looknews.util.ColorUtils;
import com.donfelix.looknews.util.DensityUtil;
import com.donfelix.looknews.util.GlideUtils;
import com.donfelix.looknews.util.ViewUtils;
import com.donfelix.looknews.util.WebUtil;
import com.donfelix.looknews.view.implpresenter.ZhihuStoryPresenterImpl;
import com.donfelix.looknews.view.implview.IZhihuStory;
import com.donfelix.looknews.view.implview.IZhihuStoryPresenter;
import com.donfelix.looknews.widget.ElasticDragDismissFrameLayout;
import com.donfelix.looknews.widget.ParallaxScrimageView;
import com.donfelix.looknews.widget.TranslateYTextView;

import java.lang.reflect.InvocationTargetException;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created by Don on 2017/4/1.
 * Desc
 */

public class ZhihuDailyDetailActivity extends BaseActivity implements IZhihuStory {

    @BindView(R.id.shot)
    ParallaxScrimageView shot;
    @BindView(R.id.title)
    TranslateYTextView title;
    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.wv_zhihu)
    WebView wvZhihu;
    @BindView(R.id.nest)
    NestedScrollView nest;
    @BindView(R.id.container)
    FrameLayout container;
    @BindView(R.id.draggable_frame)
    ElasticDragDismissFrameLayout draggableFrame;

    private float SCRIM_ADJUSTMENT = 0.075f;
    private int[] deviceInfo;
    private int width;
    private int height;
    private String id;
    private String newsTitle;
    private String shareUrl;
    private IZhihuStoryPresenter zhihuStoryPresenter;
    private ElasticDragDismissFrameLayout.SystemChromeFader systemChromeFader;
    private Transition.TransitionListener zhihuReturnHomeListener = new AnimUtils.TransitionListenerAdapter() {
        @Override
        public void onTransitionStart(Transition transition) {
            super.onTransitionStart(transition);
            toolbar.animate()
                    .alpha(0f)
                    .setDuration(100)
                    .setInterpolator(new AccelerateInterpolator());
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                shot.setElevation(1f);
                toolbar.setElevation(0f);
            }
            nest.animate()
                    .alpha(0f)
                    .setDuration(50)
                    .setInterpolator(new AccelerateInterpolator());
        }
    };
    private NestedScrollView.OnScrollChangeListener scrollChangeListener = new NestedScrollView.OnScrollChangeListener() {
        @Override
        public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            if (scrollY >= 500 + toolbar.getHeight() / 2) {
                toolbar.setTitle(newsTitle);
            } else {
                title.setOffset(-scrollY * 2);
                shot.setOffset(-oldScrollY);
                toolbar.setTitle(getResources().getString(R.string.zhihu));
            }
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_zhihu_daily_detail);
        ButterKnife.bind(this);
        deviceInfo = DensityUtil.getDeviceInfo(this);
        width = deviceInfo[0];
        height = width * 3 / 4;
        setSupportActionBar(toolbar);

        initData();
        initView();
        getNetData();

        systemChromeFader = new ElasticDragDismissFrameLayout.SystemChromeFader(this);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getWindow().getSharedElementReturnTransition().addListener(zhihuReturnHomeListener);
            getWindow().setSharedElementEnterTransition(new ChangeBounds());
        }
        enterAnimation();
    }

    private void initData() {
        Intent intent = getIntent();
        if (intent != null) {
            id = intent.getStringExtra("id");
            newsTitle = intent.getStringExtra("title");
        }
        zhihuStoryPresenter = new ZhihuStoryPresenterImpl(this);
        nest.setOnScrollChangeListener(scrollChangeListener);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            postponeEnterTransition();
            shot.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    shot.getViewTreeObserver().removeOnPreDrawListener(this);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        startPostponedEnterTransition();
                    }
                    return true;
                }
            });
        }
    }

    private void initView() {
        toolbar.setTitleMargin(20, 20, 0, 10);
        toolbar.setNavigationIcon(R.drawable.ic_arrow_back);
        toolbar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                nest.smoothScrollTo(0, 0);
            }
        });
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                expandImageAndFinish();
            }
        });
        title.setText(newsTitle);
        WebSettings settings = wvZhihu.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        settings.setLoadWithOverviewMode(true);
        settings.setBuiltInZoomControls(true);
        //settings.setUseWideViewPort(true);造成文字太小
        settings.setDomStorageEnabled(true);
        settings.setDatabaseEnabled(true);
        settings.setAppCachePath(getCacheDir().getAbsolutePath() + "/webViewCache");
        settings.setAppCacheEnabled(true);
        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        wvZhihu.setWebChromeClient(new WebChromeClient());
    }

    private void getNetData() {
        zhihuStoryPresenter.getZhihuStory(id);
    }

    @Override
    protected void onResume() {
        super.onResume();
        draggableFrame.addListener(systemChromeFader);
        try {
            wvZhihu.getClass().getMethod("onResume").invoke(wvZhihu, (Object[]) null);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        draggableFrame.addListener(systemChromeFader);
        try {
            wvZhihu.getClass().getMethod("onPause").invoke(wvZhihu, (Object[]) null);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getWindow().getSharedElementReturnTransition().removeListener(zhihuReturnHomeListener);
        }
        //webview内存泄露
        if (wvZhihu != null) {
            ((ViewGroup) wvZhihu.getParent()).removeView(wvZhihu);
            wvZhihu.destroy();
            wvZhihu = null;
        }
        zhihuStoryPresenter.unsubscribe();
        super.onDestroy();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        expandImageAndFinish();
    }

    private void expandImageAndFinish() {
        if (shot.getOffset() != 0f) {
            Animator expandImage = ObjectAnimator.ofFloat(shot, ParallaxScrimageView.OFFSET, 0f);
            expandImage.setDuration(80);
            expandImage.setInterpolator(new AccelerateInterpolator());
            expandImage.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        finishAfterTransition();
                    } else {
                        finish();
                    }
                }
            });
            expandImage.start();
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                finishAfterTransition();
            } else {
                finish();
            }
        }
    }

    private void enterAnimation() {
        int height = toolbar.getHeight();
        LinearInterpolator interpolator = new LinearInterpolator();
        viewEnterAnimation(shot, height, interpolator);
        viewEnterAnimationNest(nest, 0, interpolator);
    }

    private void viewEnterAnimation(View view, int offset, Interpolator interpolator) {
        view.setTranslationY(-offset);
        view.setAlpha(0f);
        view.animate()
                .translationY(0f)
                .alpha(1f)
                .setDuration(500L)
                .setInterpolator(interpolator)
                .setListener(null)
                .start();
    }

    private void viewEnterAnimationNest(View view, int offset, Interpolator interpolator) {
        view.setTranslationY(-offset);
        view.setAlpha(0.3f);
        view.animate()
                .translationY(0f)
                .alpha(1f)
                .setDuration(500L)
                .setInterpolator(interpolator)
                .setListener(null)
                .start();
    }

    private RequestListener<String, GlideDrawable> listener = new RequestListener<String, GlideDrawable>() {
        @Override
        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
            final Bitmap bitmap = GlideUtils.getBitmap(resource);
            int twentyFourDip = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    24, getResources().getDisplayMetrics());
            Palette.from(bitmap)
                    .maximumColorCount(3)
                    .clearFilters()
                    .setRegion(0, 0, bitmap.getWidth() - 1, twentyFourDip)
                    .generate(new Palette.PaletteAsyncListener() {
                        @Override
                        public void onGenerated(Palette palette) {
                            boolean isDark;
                            @ColorUtils.Lightness
                            int lightness = ColorUtils.isDark(palette);
                            if (lightness == ColorUtils.LIGHTNESS_UNKNOWN) {
                                isDark = ColorUtils.isDark(bitmap, bitmap.getWidth() / 2, 0);
                            } else {
                                isDark = lightness == ColorUtils.IS_DARK;
                            }
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                                int statusBarColor = getWindow().getStatusBarColor();
                                final Palette.Swatch topColor = ColorUtils.getMostPopulousSwatch(palette);
                                if (topColor != null &&
                                        (isDark || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)) {
                                    statusBarColor = ColorUtils.scrimify(topColor.getRgb(),
                                            isDark, SCRIM_ADJUSTMENT);
                                    if (!isDark && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                        ViewUtils.setLightStatusBar(shot);
                                    }
                                }

                                if (statusBarColor != getWindow().getStatusBarColor()) {
                                    shot.setScrimColor(statusBarColor);
                                    ValueAnimator statusBarColorAnim = ValueAnimator.ofArgb(
                                            getWindow().getStatusBarColor(), statusBarColor);
                                    statusBarColorAnim.addUpdateListener(new ValueAnimator
                                            .AnimatorUpdateListener() {
                                        @Override
                                        public void onAnimationUpdate(ValueAnimator animation) {
                                            getWindow().setStatusBarColor((int) animation.getAnimatedValue());
                                        }
                                    });
                                    statusBarColorAnim.setDuration(1000L);
                                    statusBarColorAnim.setInterpolator(new AccelerateInterpolator());
                                    statusBarColorAnim.start();
                                }
                            }
                        }
                    });
            Palette.from(bitmap)
                    .clearFilters()
                    .generate(new Palette.PaletteAsyncListener() {
                        @Override
                        public void onGenerated(Palette palette) {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                                shot.setForeground(ViewUtils.createRipple(palette, 0.3f, 0.6f,
                                        ContextCompat.getColor(ZhihuDailyDetailActivity.this, R.color.mid_grey),
                                        true));
                            }
                        }
                    });
            shot.setBackground(null);
            return false;
        }

        @Override
        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
            return false;
        }
    };

    @Override
    public void showStory(ZhihuStory story) {
        Glide.with(this)
                .load(story.getImage())
                .centerCrop()
                .listener(listener)
                .override(width, height)
                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                .into(shot);
        shareUrl = story.getShare_url();
        String body = story.getBody();
        String[] css = story.getCss();
        if (TextUtils.isEmpty(body)) {
            wvZhihu.loadUrl(shareUrl);
        } else {
            String data = WebUtil.buildHtmlWithCss(body, css, Config.isNight);
            wvZhihu.loadDataWithBaseURL(WebUtil.BASE_URL, data, WebUtil.MIME_TYPE, WebUtil.ENCODING, WebUtil.FAIL_URL);
        }
    }

    @Override
    public void showError(String error) {
        Snackbar.make(wvZhihu, getString(R.string.snack_infor), Snackbar.LENGTH_INDEFINITE).setAction("重试", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getNetData();
            }
        }).show();
    }
}
